////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copyright (c) 2009 - 2010 RacoonStudios
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this
/// software and associated documentation files (the "Software"), to deal in the Software
/// without restriction, including without limitation the rights to use, copy, modify, merge,
/// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
/// to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or
/// substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
/// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
/// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
/// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
/// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
/// DEALINGS IN THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
#ifndef binaryreader_h__
#define binaryreader_h__

#include "iosystem/streamreader.h"
#include "math/float2.h"
#include "math/float4.h"
#include "math/point2.h"
#include "math/point4.h"
#include "math/vector2.h"
#include "math/vector3.h"
#include "math/vector4.h"
#include "math/quaternion.h"
#include "math/line2.h"
#include "math/line3.h"
#include "math/plane.h"
#include "math/rectangle.h"
#include "math/sphere.h"
#include "math/matrix.h"
#include "system/byteorder.h"

namespace IO
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// \class	BinaryReader
	///
	/// \brief	This class provides an interface for easily reading binary data from
	///			a stream.
	///
	/// \author	Markus
	/// \date	14.02.2010
	////////////////////////////////////////////////////////////////////////////////////////////////////
	class BinaryReader : public StreamReader
	{
		RE_DeclareClass(IO::BinaryReader);

	public:

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	BinaryReader()
		///
		/// \brief	Default constructor. 
		///
		/// \author	Markus
		/// \date	14.02.2010
		////////////////////////////////////////////////////////////////////////////////////////////////////
		BinaryReader();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	virtual ~BinaryReader()
		///
		/// \brief	Finaliser. 
		///
		/// \author	Markus
		/// \date	14.02.2010
		////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual ~BinaryReader();





		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void SetMemoryMappingEnabled(bool b)
		///
		/// \brief	Sets a memory mapping mode. 
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \param	[in]	b	The memory mapping mode the stream should have.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void SetMemoryMappingEnabled(bool b);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool IsMemoryMappingEnabled() const
		///
		/// \brief	Determines if memory mapping is enabled for the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	True if memory mapping is enabled of the stream, otherwise false.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool IsMemoryMappingEnabled() const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void SetStreamEndianess(System::ByteOrder::Type order)
		///
		/// \brief	Sets the stream endianess.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \param	[in]	order	The endianess the stream should have. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void SetStreamEndianess(System::ByteOrder::Type order);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	System::ByteOrder::Type GetStreamEndianess() const
		///
		/// \brief	Returns the stream endianess. 
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The stream endianess.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		System::ByteOrder::Type GetStreamEndianess() const;





		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	virtual bool Open()
		///
		/// \brief	Opens the binary writer.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	True if the binary reader was opened successfully, otherwise false.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Open();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	virtual void Close()
		///
		/// \brief	Closes the binary reader.
		///
		/// \author	Markus
		/// \date	14.02.2010
		////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual void Close();





		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	char ReadChar()
		///
		/// \brief	This reads a char from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The char we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		char ReadChar();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	uchar ReadUChar()
		///
		/// \brief	This reads a uchar from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The uchar we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		uchar ReadUChar();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	short ReadShort()
		///
		/// \brief	This reads a short from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The short we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		short ReadShort();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	ushort ReadUShort()
		///
		/// \brief	This reads a ushort frmo the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The ushort we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		ushort ReadUShort();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	int ReadInt()
		///
		/// \brief	Reads the int. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The int. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		int ReadInt();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	uint ReadUInt()
		///
		/// \brief	Reads the u int. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The u int. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		uint ReadUInt();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	float ReadFloat()
		///
		/// \brief	This reads a float from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The float we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		float ReadFloat();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	double ReadDouble()
		///
		/// \brief	This reads a double from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The double we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		double ReadDouble();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool ReadBool()
		///
		/// \brief	This reads a bool from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The bool we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool ReadBool();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Helper::String ReadString()
		///
		/// \brief	This reads a String from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The string we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Helper::String ReadString();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::float2 ReadFloat2()
		///
		/// \brief	This reads a float2 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The float2 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::float2 ReadFloat2();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::float4 ReadFloat4()
		///
		/// \brief	This reads a float4 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The float4 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::float4 ReadFloat4();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::point2 ReadPoint2()
		///
		/// \brief	This reads a point2 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The point2 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::point2 ReadPoint2();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::point4 ReadPoint4()
		///
		/// \brief	This reads a point4 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The point4 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::point4 ReadPoint4();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::vector2 ReadVector2()
		///
		/// \brief	This reads a vector2 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The vector2 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::vector2 ReadVector2();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::vector3 ReadVector3()
		///
		/// \brief	This reads a vector3 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The vector3 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::vector3 ReadVector3();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::vector4 ReadVector4()
		///
		/// \brief	This reads a vector4 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The vector4 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::vector4 ReadVector4();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::quaternion ReadQuaternion()
		///
		/// \brief	This reads a quaternion from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The quaternion we've read from the steam.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::quaternion ReadQuaternion();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::plane ReadPlane()
		///
		/// \brief	This reads a plane from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The plane we*ve read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::plane ReadPlane();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::line2 ReadLine2()
		///
		/// \brief	This reads a line2 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The line2 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::line2 ReadLine2();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::line3 ReadLine3()
		///
		/// \brief	This reads a line3 from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The line3 we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::line3 ReadLine3();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::rectangle<int> ReadIntRectangle()
		///
		/// \brief	This reads a int rectangle from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The int rectangle we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::rectangle<int> ReadIntRectangle();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::rectangle<float> ReadFloatRectangle()
		///
		/// \brief	This reads a float rectangle from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The float rectangle we've read from the stream.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::rectangle<float> ReadFloatRectangle();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::sphere ReadSphere()
		///
		/// \brief	This reads a sphere from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The sphere we've read from the stream. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::sphere ReadSphere();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	Math::matrix ReadMatrix()
		///
		/// \brief	This reads a matrix from the stream.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \return	The matrix44 we've read from the stream. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		Math::matrix ReadMatrix();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void ReadRawData(void * ptr, tSize bytes)
		///
		/// \brief	This read a specified amount of bytes and saves it to a specified 
		///			memory block.
		///
		/// \author	Markus
		/// \date	14.02.2010
		///
		/// \param	[out]	ptr		Pointer towards a memory block where we can save the data.
		/// \param	[in]	bytes	The amount of bytes we want to read.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void ReadRawData(void * ptr, tSize bytes);




		System::ByteOrder m_byteOrder;
		uchar * m_mapCursor;
		uchar * m_mapEnd;

		bool m_enableMapping;
		bool m_isMapped;

	protected:

	private:

	};

}

#endif // binaryreader_h__